///
/// AEye, Inc. ("COMPANY") CONFIDENTIAL
/// Unpublished Copyright (c) 2013-2023 AEye, Inc., All Rights Reserved.
///
/// NOTICE:  All information contained herein is, and remains the property of COMPANY.
/// The intellectual and technical concepts contained herein are proprietary to COMPANY and
/// may be covered by U.S. and Foreign Patents, patents in process, and are protected by trade secret or copyright law.
/// Dissemination of this information or reproduction of this material is strictly forbidden unless
/// prior written permission is obtained from COMPANY.
/// Access to the source code contained herein is hereby forbidden to anyone except current COMPANY employees, managers,
/// or contractors who have executed Confidentiality and Non-disclosure agreements explicitly covering such access.
///
/// The copyright notice above does not evidence any actual or intended publication or disclosure of this source code,
/// which includes information that is confidential and/or proprietary, and is a trade secret, of  COMPANY.
/// ANY REPRODUCTION, MODIFICATION, DISTRIBUTION, PUBLIC PERFORMANCE, OR PUBLIC DISPLAY OF OR THROUGH USE OF THIS
/// SOURCE CODE WITHOUT THE EXPRESS WRITTEN CONSENT OF COMPANY IS STRICTLY PROHIBITED, AND IN VIOLATION OF APPLICABLE
/// LAWS AND INTERNATIONAL TREATIES. THE RECEIPT OR POSSESSION OF THIS SOURCE CODE AND/OR RELATED INFORMATION DOES NOT
/// CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE, DISCLOSE, OR DISTRIBUTE ITS CONTENTS, OR TO MANUFACTURE, USE, OR SELL
/// ANYTHING THAT IT  MAY DESCRIBE, IN WHOLE OR IN PART.
///

/// @file AEyeSDKStructures.hpp

#ifndef AEYESDKSTRUCTURES_HPP
#define AEYESDKSTRUCTURES_HPP

#include <cstdint>
#include <string>

#include "PointStructure.hpp"

//==============================================================================
//=                            Point Return Packets                            =
//==============================================================================

namespace aeye {

/// @cond IGNORE
static constexpr uint16_t DEFAULT_COMMAND_PORT        = 7000;
static constexpr uint16_t DEFAULT_CLIENT_POINTS_PORT  = 7001;
static constexpr uint16_t DEFAULT_CLIENT_IMAGE_PORT   = 7002;
static constexpr uint16_t DEFAULT_CLIENT_HAWKEYE_PORT = 7003;
/// @endcond

/// @brief Port of the sensor used to stream point cloud data
static constexpr uint16_t DEFAULT_SERVER_POINTS_PORT  = 7001;
/// @cond UNSUPPORTED
/// @brief Port of the sensor used to stream camera data
static constexpr uint16_t DEFAULT_SERVER_IMAGE_PORT   = 7002;
/// @cond IGNORE
static constexpr uint16_t DEFAULT_SERVER_HAWKEYE_PORT = 7003;
/// @endcond
/// @brief Port of the sensor used to stream diagnostics data
static constexpr uint16_t DEFAULT_DIAGNOSTIC_PORT     = 7004;
/// @endcond
  /// @enum AEye LiDAR TCP Response Statuses
  enum class ReturnStatus : int16_t {  // uses in commands responses as returning value.
    NO_ERRORS                   =  0,
    GENERIC_ERROR               = -1,
    /// @cond UNSUPPORTED
    ALREADY_RUNNING             = -2,
    NOT_RUNNING                 = -3,
    COULD_NOT_CREATE_THREAD     = -4,
    ZERO_POINTS                 = -5,
    BAD_SHOTLIST                = -6,
    /// @endcond
    NETWORK_ERROR               = -8,
    UNKNOWN_COMMAND             = -9,
    INCORRECT_PACKET_SIZE       = -10,
    BAD_PARAMETER               = -11,
    EYESAFETY_SHUTDOWN_OCCURRED = -12,
    UNSUPPORTED_VERSION         = -13,
    AUTOMATIC_STATE_CHANGE      = -14,
    DISALLOWED_COMMAND          = -15,
    BAD_FILE                    = -16,
    LASER_ERROR                 = -17,
    CONFIG_ERROR                = -18,
    NOT_IMPLEMENTED_YET         = -20,
  };

  /// @enum Passive Sensing Subsystem Patterns
  enum PassiveModeFlags : uint8_t {
    DISABLED             = 0b00000000, //!< No pattern.
    /// @cond UNSUPPORTED
    GRID                 = 0b00000001, //!< Grid pattern.
    RANDOM               = 0b00000010, //!< Uniformly distributed pseudorandom pattern.
    OFFSET_GRID          = 0b00000100, //!< Grid pattern with offset.
    FOVEATED_GRID        = 0b00001000, //!< Vertically and horizontally Foveated pattern around some center point.
    FOVEATED_RANDOM      = 0b00010000, //!< Foveally distributed pseudorandom pattern.
    MOVING_GRID          = 0b00100000, //!< Grid pattern with changing offsets.
    /// @endcond
    SHOTLIST_FROM_FILE   = 0b01000000, //!< Get shotlist pattern from file.
  };

  /// @cond UNSUPPORTED

#ifdef _MSC_VER
#pragma pack(push,1)
#endif
  /// @typedef AEye Sensor Active Zone helper struct
  struct Quadrilateral {
    uint16_t      topLeftX;
    uint16_t      topLeftY;
    uint16_t      topRightX;
    uint16_t      topRightY;
    uint16_t      btmLeftX;
    uint16_t      btmLeftY;
    uint16_t      btmRightX;
    uint16_t      btmRightY;
  } ATTRIBUTE_PACKED;

  /// @endcond
#ifdef _MSC_VER
#pragma pack(pop)
#endif

  /// @enum Passive Mode Parameters
  enum class PassiveModeParam : uint8_t {
    /// @cond UNSUPPORTED
    // Simple grid
    GRID_ROW_NUM, //!< Number of grid rows to fire at in grid pattern
    GRID_COL_NUM, //!< Number of grid columns to fire at in grid pattern
    // Simple random
    RANDOM_ROW_NUM, //!< Number of rows used for random pattern
    RANDOM_COL_NUM, //!< Number of columns used for random pattern
    // Offset grid
    OFFSET_GRID_ROW_NUM, //!< Number of grid rows to fire at in offset grid pattern
    OFFSET_GRID_COL_NUM, //!< Number of grid columns to fire at in offset grid pattern
    GRID_COLUMN_OFFSET, //!< number of columns to skip row-by-row
    // Moving grid
    MOVING_GRID_ROW_NUM, //!< Number of grid rows to fire at in moving grid pattern
    MOVING_GRID_COL_NUM, //!< Number of grid columns to fire at in moving grid pattern
    GRID_COL_SPEED, //!< Speed or rate at which the column offset increases
    GRID_ROW_SPEED, //!< Speed or rate at which the row offset increases
    // Foveated grid
    FOVEATED_GRID_ROW_NUM, //!< Number of grid rows to fire at in foveated grid pattern
    FOVEATED_GRID_COL_NUM, //!< Number of grid columns to fire at in foveated grid pattern
    GRID_FOVEATION_COEFFICIENT_COL, //!< Foveation coefficient for non-linearity in the columns in the foveated grid pattern
    GRID_FOVEATION_COEFFICIENT_ROW, //!< Foveation coefficient for non-linearity in the rows in the foveated grid pattern
    FOVEATED_GRID_CENTER_COL, //!< Focus of the foveated grid pattern (column)
    FOVEATED_GRID_CENTER_ROW, //!< Focus of the foveated grid pattern (row)
    // Foveated random
    FOVEATED_RANDOM_ROW_NUM, //!< Number of rows to fire at in foveated grid pattern
    FOVEATED_RANDOM_COL_NUM, //!< Number of columns to fire at in foveated grid pattern
    RANDOM_FOVEATION_COEFFICIENT_COL, //!< Foveation coefficient for non-linearity in the columns in the foveated random pattern
    RANDOM_FOVEATION_COEFFICIENT_ROW, //!< Foveation coefficient for non-linearity in the rows in the foveated random pattern
    FOVEATED_RANDOM_CENTER_COL, //!< Focus of the foveated random pattern (column)
    FOVEATED_RANDOM_CENTER_ROW, //!< Focus of the foveated random pattern (row)
    /// @endcond
    // Embedded shotlist
    SHOTLIST_FILE_NUMBER, //!< Shotlist files stored in the device. 0-based index.
  };

  /// @enum PointFlags
  enum class PointFlags : uint32_t {
    ECHO_LSB = (1U << 0U),                    //!< LSB for Echo Return 1-4
    ECHO_MSB = (1U << 1U),
    RESERVED1 = (1U << 2U),
    RESERVED2 = (1U << 3U),
    RESERVED3 = (1U << 4U),
    RESERVED4 = (1U << 5U),
    RESERVED5 = (1U << 6U),
    RESERVED6 = (1U << 7U),
    RESERVED7 = (1U << 8U),
    RESERVED8 = (1U << 9U),
    RESERVED9 = (1U << 10U),
    RESERVED10 = (1U << 11U),
    RESERVED11 = (1U << 12U),
    RESERVED12 = (1U << 13U),
    RESERVED13 = (1U << 14U),
    RESERVED14 = (1U << 15U),
    RESERVED15 = (1U << 16U),
    RESERVED16 = (1U << 17U),
    RESERVED17 = (1U << 18U),
    RESERVED18 = (1U << 19U),
    RESERVED19 = (1U << 20U),
    RESERVED20 = (1U << 21U),
    RESERVED21 = (1U << 22U),
    RESERVED22 = (1U << 23U),
    RESERVED23 = (1U << 24U),
    RESERVED24 = (1U << 25U),
    RESERVED25 = (1U << 26U),
    RESERVED26 = (1U << 27U),
    RESERVED27 = (1U << 28U),
    RESERVED28 = (1U << 29U),
    RESERVED29 = (1U << 30U),
    RESERVED30 = (1U << 31U)
  };

  /// @enum AEye Sensor Model Types (16 bits)
  /// Upper 8 bits are Product ID
  /// Lower 8 bits are Variant ID * 16 plus Version number
  enum class ModelType : uint16_t {
        UNKNOWN    = 0,       //!< Unknown or Invalid hardware (error condition)
        FSM60A     = 0x0300,  //!< Generation 2 Hardware
        FSM60B     = FSM60A + 1U,
        FSM120     = 0x0400,
        RESERVED_1 = 0x0500,
        RESERVED_2 = RESERVED_1 + 1U,
        APOLLO_A1  = 0x0600,
        APOLLO_A2  = APOLLO_A1 + 1U,
        APOLLO_B0  = APOLLO_A2 + 1U,
        VIRTUAL  = 0xFFFF,  //! Virtual <PCAP file player
  };

  enum class MultiEchoMode : uint8_t {
    FIRST     = 0x00, //!< First, Last, Strongest, next Largest.
    STRONGEST = 0x01, //!< Strongest, 2 nd Strongest, 3rd Strongest, 4th Strongest.
  };

  ///@enum Time Server Status Return Parameters
  enum class TimeServerStatus : uint8_t {
      SYNCHRONIZED     = 0x00,   //!< Actively Synchronized to NTP/PTP/gPTP Server
      DESYNCHRONIZED   = 0x01,   //!< Desynchronized from NTP/PTP/gPTP Server
      INDETERMINATE    = 0x02,   //!< Indeterminate state from NTP/PTP/gPTP Server
      OFF              = 0x03    //!< NTP/PTP/gPTP daemon is off
  };

  struct GptpServerStatus {
      TimeServerStatus GPTPstatus; //!< 0 - synchronized, 1 - not synchronized, 2 - clock state is indeterminate
      std::string stepsRemoved; //!< The number of communication paths to the grandmaster clock
      float offsetFromMaster; //!< The last measured offset of the clock from the master in nanoseconds
      float meanPathDelay; //!< The estimated delay of the synchronization messages sent from the master in nanoseconds
      float masterOffset; //!< The last measured offset of the clock from the master in nanoseconds
      std::string ingressTime; //!< The "ingress" time stamp of the most recently received sync message
      float cumulativeScaledRateOffset; //!< The calculated scaled rate offset to ensure master-slave sync
      std::string scaledLastGmPhaserChange; //!< The calculated scaled grandmaster phase change to ensure master-slave sync
      std::string gmPresent; //!< If true, the gPTP clock is synchronized to a master and the local clock is not the grandmaster
      std::string gmIdentity; //!< The grandmaster's identity, displayed as an address
      std::string portIdentity; //!< The slave identity i.e. sensor identity, displayed as an address
      std::string portState; //!< The active state of the sensor port, INITIALIZING, LISTENING, UNCALIBRATED, or SLAVE
      std::string logMinDelayRequestInterval; //!< The minimum permitted mean time interval between Delay_Req messages
      std::string peerMeanPathDelay; //!< The mean path delay of messages through the system, calculated between peers
      std::string logAnnounceInterval; //!< The mean time interval between Announce messages
      std::string announceReceiptTimeout; //!< The number of missed Announce messages before the last Announce messages expires
      std::string logSyncInterval; //!< The mean time interval between Sync messages
      std::string delayMechanism; //!< The delay mechanism, for gPTP this is automaticall set to P2P
      std::string logMindPdelayReqInterval; //!< The minimum permitted mean time interval between Pdelay_Req messages
      std::string versionNumber; //!< The current version of the ptp4l application
  };

  /// @brief used to assert that you are indeed using a 4SightM sensor
  inline uint8_t GetMajorHwVersion(ModelType hwModel) { return (static_cast<uint16_t>(hwModel) & 0x7F00U) >> 8U; }
  /// @cond UNSUPPORTED
  inline uint8_t GetMinorHwVersion(ModelType hwModel) { return (static_cast<uint16_t>(hwModel) & 0x00f0U) >> 4U; }
  inline bool IsVirtualSensor(ModelType hwModel) { return static_cast<uint16_t>(hwModel) == 0xFFFF; }
  /// @endcond

  /// @brief Specifies position and orientation.
  typedef struct {
      double x; ///< The axis looking out of the barrel of the sensor. (Front)
      double y; ///< The axis which is neither x nor z. (Left)
      double z; ///< The vertical axis. (Up)
      double yaw; ///< Rotation about the z axis.
      double pitch; ///< Rotation about the y axis.
      double roll; ///< Rotation about the x axis.
  } ATTRIBUTE_PACKED Pose;
}

#endif //AEYESDKSTRUCTURES_HPP
